package com.knife.oauth.util;

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;

import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @author tianhao.luo@hand-china.com
 * @version 1.0
 * @date 2022年04月16日 星期六 5:10 下午
 * @description
 * @since 1.0
 */
@Slf4j
public class KnifeRsaKeyUtil {

    private final static Base64.Encoder base64Encoder = Base64.getEncoder();
    private final static Base64.Decoder base64Decoder = Base64.getDecoder();

    public static void main(String[] args) throws Exception {
        logRsaKey();
    }

    public static void logRsaKey() throws Exception {
        RSAKeyGenerator rsaKeyGenerator = new RSAKeyGenerator(2048);
        RSAKey generate = rsaKeyGenerator.generate();
        RSAPrivateKey rsaPrivateKey = generate.toRSAPrivateKey();
        log.info("私钥:{}", new String(base64Encoder.encode(rsaPrivateKey.getEncoded())));
        RSAPublicKey rsaPublicKey = generate.toRSAPublicKey();
        log.info("公钥:{}", new String(base64Encoder.encode(rsaPublicKey.getEncoded())));
    }


    public static RSAPublicKey createRsaPublicKeyByStr(String publicKeyBase64) throws Exception {
        byte[] publicBytes = base64Decoder.decode(publicKeyBase64);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    }


    public static RSAPrivateKey createRsaPrivateKeyByStr(String privateKeyBase64) throws Exception {
        byte[] privateBytes = base64Decoder.decode(privateKeyBase64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    }

    public static RSAKey createRsaKey(RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey) {
        RSAKey.Builder builder = new RSAKey.Builder(rsaPublicKey);
        return builder.privateKey(rsaPrivateKey).build();
    }

    public static NimbusJwtEncoder createJwtEncoder(RSAKey rsaKey) {
        return new NimbusJwtEncoder(new ImmutableJWKSet<>(new JWKSet(rsaKey)));
    }

    public static NimbusJwtDecoder createJwtDecoder(RSAPublicKey rsaPublicKey) {
        return NimbusJwtDecoder.withPublicKey(rsaPublicKey).build();
    }
}
